package com.smart.community.commons.utils;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
 * Redis工具类
 * @author Wu.Liang
 * @since 2024-12-19
 * @version 1.0.0
 */
@Slf4j
@Component
public class RedisUtil {
    
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
    
    /**
     * 设置缓存
     * 
     * @param key 键
     * @param value 值
     */
    public void set(String key, Object value) {
        redisTemplate.opsForValue().set(key, value);
    }
    
    /**
     * 设置缓存并设置过期时间
     * 
     * @param key 键
     * @param value 值
     * @param timeout 过期时间
     * @param unit 时间单位
     */
    public void set(String key, Object value, long timeout, TimeUnit unit) {
        redisTemplate.opsForValue().set(key, value, timeout, unit);
    }
    
    /**
     * 获取缓存
     * 
     * @param key 键
     * @return 值
     */
    public Object get(String key) {
        return redisTemplate.opsForValue().get(key);
    }
    
    /**
     * 删除缓存
     * 
     * @param key 键
     * @return 是否成功
     */
    public boolean delete(String key) {
        try {
            Boolean result = redisTemplate.delete(key);
            log.debug("Redis删除缓存: {} = {}", key, result);
            return result != null && result;
        } catch (Exception e) {
            log.error("Redis删除缓存失败: {}", key, e);
            return false;
        }
    }
    
    /**
     * 删除缓存（del方法别名）
     * 
     * @param key 键
     * @return 是否成功
     */
    public boolean del(String key) {
        return delete(key);
    }
    
    /**
     * 批量删除缓存
     * 
     * @param keys 键集合
     * @return 删除数量
     */
    public long delete(Collection<String> keys) {
        try {
            Long result = redisTemplate.delete(keys);
            log.debug("Redis批量删除缓存: {} = {}", keys, result);
            return result != null ? result : 0;
        } catch (Exception e) {
            log.error("Redis批量删除缓存失败: {}", keys, e);
            return 0;
        }
    }
    
    /**
     * 批量删除缓存（别名方法）
     * 
     * @param keys 键集合
     * @return 删除数量
     */
    public long batchDelete(Collection<String> keys) {
        return delete(keys);
    }
    
    /**
     * 判断键是否存在
     * 
     * @param key 键
     * @return 是否存在
     */
    public boolean hasKey(String key) {
        return Boolean.TRUE.equals(redisTemplate.hasKey(key));
    }
    
    /**
     * 设置过期时间
     * 
     * @param key 键
     * @param timeout 过期时间
     * @param unit 时间单位
     * @return 是否成功
     */
    public boolean expire(String key, long timeout, TimeUnit unit) {
        return Boolean.TRUE.equals(redisTemplate.expire(key, timeout, unit));
    }
    
    /**
     * 获取过期时间
     * 
     * @param key 键
     * @return 过期时间（秒）
     */
    public long getExpire(String key) {
        try {
            Long result = redisTemplate.getExpire(key);
            log.debug("Redis获取过期时间: {} = {}", key, result);
            return result != null ? result : -1;
        } catch (Exception e) {
            log.error("Redis获取过期时间失败: {}", key, e);
            return -1;
        }
    }
    
    /**
     * 获取所有匹配的键
     * 
     * @param pattern 匹配模式
     * @return 键集合
     */
    public Set<String> keys(String pattern) {
        return redisTemplate.keys(pattern);
    }
    
    /**
     * 递增
     * 
     * @param key 键
     * @param delta 增量
     * @return 递增后的值
     */
    public long increment(String key, long delta) {
        return redisTemplate.opsForValue().increment(key, delta);
    }
    
    /**
     * 递减
     * 
     * @param key 键
     * @param delta 减量
     * @return 递减后的值
     */
    public long decrement(String key, long delta) {
        return redisTemplate.opsForValue().increment(key, -delta);
    }
    
    /**
     * 获取Hash中的所有字段
     * 
     * @param key 键
     * @return 字段映射
     */
    public Map<Object, Object> hGetAll(String key) {
        return redisTemplate.opsForHash().entries(key);
    }
    
    /**
     * 设置Hash字段
     * 
     * @param key 键
     * @param hashKey 字段键
     * @param value 字段值
     */
    public void hSet(String key, String hashKey, Object value) {
        redisTemplate.opsForHash().put(key, hashKey, value);
    }
    
    /**
     * 获取Hash字段
     * 
     * @param key 键
     * @param hashKey 字段键
     * @return 字段值
     */
    public Object hGet(String key, String hashKey) {
        return redisTemplate.opsForHash().get(key, hashKey);
    }
    
    /**
     * 删除Hash字段
     * 
     * @param key 键
     * @param hashKeys 字段键数组
     * @return 删除数量
     */
    public long hDelete(String key, Object... hashKeys) {
        try {
            Long result = redisTemplate.opsForHash().delete(key, hashKeys);
            log.debug("Redis删除Hash字段: {}.{} = {}", key, hashKeys, result);
            return result != null ? result : 0;
        } catch (Exception e) {
            log.error("Redis删除Hash字段失败: {}.{}", key, hashKeys, e);
            return 0;
        }
    }
    
    /**
     * 判断Hash字段是否存在
     * 
     * @param key 键
     * @param hashKey 字段键
     * @return 是否存在
     */
    public boolean hHasKey(String key, String hashKey) {
        return Boolean.TRUE.equals(redisTemplate.opsForHash().hasKey(key, hashKey));
    }
    
    /**
     * 获取List
     * 
     * @param key 键
     * @param start 开始位置
     * @param end 结束位置
     * @return 列表
     */
    public List<Object> lRange(String key, long start, long end) {
        return redisTemplate.opsForList().range(key, start, end);
    }
    
    /**
     * 获取List长度
     * 
     * @param key 键
     * @return 长度
     */
    public long lSize(String key) {
        try {
            Long result = redisTemplate.opsForList().size(key);
            log.debug("Redis获取List长度: {} = {}", key, result);
            return result != null ? result : 0;
        } catch (Exception e) {
            log.error("Redis获取List长度失败: {}", key, e);
            return 0;
        }
    }
    
    /**
     * 获取List指定位置的元素
     * 
     * @param key 键
     * @param index 位置
     * @return 元素
     */
    public Object lIndex(String key, long index) {
        try {
            Object result = redisTemplate.opsForList().index(key, index);
            log.debug("Redis获取List元素: {}[{}] = {}", key, index, result);
            return result;
        } catch (Exception e) {
            log.error("Redis获取List元素失败: {}[{}]", key, index, e);
            return null;
        }
    }
    
    /**
     * 设置List指定位置的元素
     * 
     * @param key 键
     * @param index 位置
     * @param value 值
     */
    public void lSet(String key, long index, Object value) {
        try {
            redisTemplate.opsForList().set(key, index, value);
            log.debug("Redis设置List元素: {}[{}] = {}", key, index, value);
        } catch (Exception e) {
            log.error("Redis设置List元素失败: {}[{}]", key, index, e);
        }
    }
    
    /**
     * 移除List中指定数量的元素
     * 
     * @param key 键
     * @param count 数量
     * @param value 值
     * @return 移除数量
     */
    public long lRemove(String key, long count, Object value) {
        try {
            Long result = redisTemplate.opsForList().remove(key, count, value);
            log.debug("Redis移除List元素: {} count={} value={} = {}", key, count, value, result);
            return result != null ? result : 0;
        } catch (Exception e) {
            log.error("Redis移除List元素失败: {}", key, e);
            return 0;
        }
    }
}
